<!DOCTYPE html>
<html lang="en">
  <head><!-- 文档元信息：给浏览器、搜索引擎等机器阅读 -->
    <!-- 文档字符编码格式 -->
    <meta charset="UTF-8" />
    <!-- 文档标题 -->
    <title>HTML / CSS / JavaScript & React Quick Guide</title>
    <link rel="icon" type="image/svg+xml" href="/week03/ppt/assets/favicon.17e50649.svg" />
    <meta name="description" content="Slides: HTML / CSS / JavaScript & React Quick Guide">
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
    <!-- 移动端事实标准 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <script type="module" crossorigin src="/week03/ppt/assets/index.75d48a5f.js"></script>
    <link rel="stylesheet" href="/week03/ppt/assets/index.a9897203.css">
  </head>
  <body><!-- 文档内容：给人阅读 -->
    <!-- HTML PPT 标记 -->
    <div class="reveal">
      <!-- HTML PPT 容器 -->
      <div class="slides">
        <!-- #region 技术分享的主题 -->
        <section class="slide tech-topic" data-background-image="assets/bg-2.jpeg" data-background-opacity="0.3">
          <h1>我们都在用相同的材料做东西</h1>
          <figure class="md:flex rounded-xl p-8 md:p-0">
            <img class="w-48 h-48 rounded-full md-auto mx-auto mt-3.5" src="assets/author.jpg" />
            <div class="px-8 text-center md:text-left">
              <p class="font-bold text-5xl">
                <span class="font-light">Web前端开发系列技术培训 之</span><br />
                HTML / CSS / JavaScript & React
              </p>
              <figcaption class="font-medium">
                王士江
                <span class="font-light"> — 前端平台研发团队</span>
              </figcaption>
            </div>
          </figure>
        </section>
        <!-- #endregion 技术分享的主题 -->

        <!-- #region Intro Guide -->
        <section class="slide intro-guide">
          <section class="slide" data-background-color="#f2f2f2">
            <h1>大前端分层架构</h1>
            <img class="w-3/4" src="assets/excalidraw/大前端分层架构.svg">
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>前端开发技术&工程/工具</h2>
            <img class="w-auto" src="assets/excalidraw/前端技术&工程工具.svg">
          </section>
        </section>
        <!-- #endregion Intro Guide -->
      
        <!-- #region HTML Guide -->
        <section class="slide html-guide">
          <section class="slide" data-background-color="#348fd4">
            <h1>HTML</h1>
            <p>
              HTML —— HyperText Markup Language， <br/>
              超级文本标记语言。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h1>HTML</h1>
            <img src="assets/html/syntax.jpeg">
            <img src="assets/html/syntax-with-attribute.jpeg">
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>HTML的功能主要由标签来承担</h2>
            <ul>
              <li>文档元信息：通常是出现在 head 标签中的元素，包含了描述文档自身的一些信息；</li>
              <li>语义相关标签：扩展了纯文本，表达文章结构、不同语言要素的标签；</li>
              <li>链接：提供到文档内和文档外的链接；</li>
              <li>替换型标签：引入声音、图片、视频等外部元素替换自身的一类标签；</li>
              <li>表单：用于填写和提交信息的一类标签；</li>
              <li>表格：表头、表尾、单元格等表格的结构。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>head：元信息的容器</h2>
            <p>
              head 标签本身并不携带任何信息，
              它主要是作为盛放其它语义类标签的容器使用。
            </p>
            <p>
              head 标签规定了自身必须是 html 标签中的第一个标签，<br/>
              它的内容必须包含一个 title，并且最多只能包含一个 base。
            </p>
            <p>
              元信息多数情况下是给浏览器、搜索引擎等机器阅读的，
              有时候这些信息会在页面之外显示给用户，有时候则不会。
            </p>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>title：文档标题</h2>
            <p>
              title 标签表示文档的标题。
            </p>
            <p>
              title 作为元信息，可能会被用在浏览器收藏夹、微信推送卡片、微博等各种场景。
            </p>
          </section>
          <section class="slide">
            <h2>base：页面的基准 URL</h2>
            <p>
              base标签的作用是给页面上所有的 URL 相对地址提供一个基础。
            </p>
            <p>
              base 标签最多只有一个，它改变全局的链接地址。
            </p>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>meta: 元信息通用标签</h2>
            <p>
              meta 标签是一组键值对，它是一种通用的元信息表示标签。
            </p>
            <p>
              在 head 中可以出现任意多个 meta 标签。<br/>
              一般的 meta 标签由 name 和 content 两个属性来定义。<br/>
              name 表示元信息的名，content 则用于表示元信息的值。
            </p>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>具有 charset 属性的 meta</h2>
            <p>
              从 HTML5 开始，为了简化写法，meta 标签新增了 charset 属性。
              添加了 charset 属性的 meta 标签无需再有 name 和 content。<br />
            </p>
            <p>
              <code>&lt;meta charset="UTF-8" &gt;</code>
            </p>
            <p>
              charset 型 meta 标签非常关键，它描述了 HTML 文档自身的编码形式。
            </p>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>name 为 viewport 的 meta</h2>
            <p>
              这类 meta 的 name 属性为 viewport，它的 content 是一个复杂结构，
              是用逗号分隔的键值对，键值对的格式是 key=value，
              它没有在 HTML 标准中定义，却是移动端开发的事实标准
            </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"&gt;
            </code></pre>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>name 为 viewport 的 meta</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"&gt;
            </code></pre>
            <ul>
              <li>width：页面宽度，可以取值具体的数字，也可以是 device-width，表示跟设备宽度相等。</li>
              <li>height：页面高度，可以取值具体的数字，也可以是 device-height，表示跟设备高度相等。</li>
              <li>initial-scale：初始缩放比例。</li>
              <li>minimum-scale：最小缩放比例。</li>
              <li>maximum-scale：最大缩放比例。</li>
              <li>user-scalable：是否允许用户缩放。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>语义相关标签</h2>
            <p>
              HTML 最初的设计场景就是“超文本”。
            </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;body&gt;
                &lt;header&gt;
                    &lt;nav&gt;……&lt;/nav&gt;
                &lt;/header&gt;
                &lt;aside&gt;
                    &lt;nav&gt;……&lt;/nav&gt;
                &lt;/aside&gt;
                &lt;section&gt;……&lt;/section&gt;
                &lt;section&gt;……&lt;/section&gt;
                &lt;section&gt;……&lt;/section&gt;
                &lt;footer&gt;……&lt;/footer&gt;
              &lt;/body&gt;  
            </code></pre>
          </section>
          <section class="slide">
            <h2>header</h2>
            <p>
              header，通常出现在前部，表示导航或者介绍性的内容。
            </p>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>footer</h2>
            <p>
              footer，通常出现在尾部，包含一些作者信息、相关链接、版权信息等。
            </p>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>aside</h2>
            <p>
              aside 表示跟文章主体不那么相关的部分，它可能包含导航、广告等工具性质的内容。
            </p>
            <p>
              aside 和 header 中都可能出现导航（nav 标签），二者的区别是，
              header 中的导航多数是到文章自己的目录，
              而 aside 中的导航多数是到关联页面或者是整站地图。
            </p>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>h1-h6</h2>
            <p>
              h1-h6 是最基本的标题，它们表示了文章中不同层级的标题。
            </p>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>p</h2>
            <p>
              p, paragraph, 普通的段落。
            </p>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>pre</h2>
            <p>
              pre 标签，表示这部分内容是预先排版过的，不需要浏览器进行排版。
            </p>
          </section>
          <section class="slide">
            <h2>code</h2>
            <p>
              code标签包裹代码。
            </p>
          </section>
          <section class="slide" data-background-image="assets/bg_tiles.jpg">
            <h2>图片</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;img src="assets/bg_tiles_color.jpg" /&gt;
            </code></pre>
            <img class="w-1/2" src="assets/bg_tiles_color.jpg" />
          </section>
          <section class="slide" data-background-video="assets/video-background.mp4" 
              data-background-video-loop  data-background-video-muted>
            <h2>视频</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;video&gt;
                &lt;source src="assets/video-background.mp4"&gt;
              &lt;/video&gt;
            </code></pre>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>表单</h2>
            <p>
              form / input / radio / checkbox ...
            </p>
            <img class="w-1/2" src="assets/html/form.png" />
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>表格</h2>
            <p>
              table / tr / th / td。
            </p>
            <img class="w-1/2" src="assets/html/table.png" />
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>SVG</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;svg xmlns="http://www.w3.org/2000/svg" version="1.1"&gt;
                &lt;circle cx="100" cy="50" r="40" stroke="black"
                stroke-width="2" fill="orange" /&gt;
              &lt;/svg&gt;
            </code></pre>
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
              <circle cx="100" cy="50" r="40" stroke="black"
              stroke-width="2" fill="orange" />
            </svg>
          </section>
          <section class="slide" data-background-iframe="examples/canvas-background/index.html">
            <h2>Canvas</h2>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>iframe</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;iframe src="examples/canvas-background/index.html"&gt;&lt;/iframe&gt;
            </code></pre>
            <iframe src="examples/canvas-background/index.html"></iframe>
          </section>
        </section>
        <!-- #endregion HTML Guide -->

        <!-- #region CSS Guide -->
        <section class="slide css-guide">
          <section class="slide" data-background-color="#06406c">
            <h1>CSS</h1>
            <p>
              CSS —— CSS Cascade Style Sheets <br/>
              层叠/级联样式表
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h1>CSS</h1>
            <img src="assets/css/syntax.jpeg">
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>类型选择器</h2>
            <p>
              根据一个元素的标签名来选中元素。
            </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              div {

              }
            </code></pre>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>全体选择器</h2>
            <p>
              与类型选择器类似，选择任意元素。
            </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              * {

              }
            </code></pre>
          </section>
          <section class="slide">
            <h2>id 选择器</h2>
            <p>
              # 后面跟随 id 名。
            </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              #myid {
                stroke:blue;
                stroke-width:1;
              }
            </code></pre>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>class 选择器</h2>
            <p>
              . 后面跟随 class 名。
            </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              .mycls {
                font-size:40px
              }
            </code></pre>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>属性选择器</h2>
            <ul>
              <li>
                第一种，[att]
              直接在方括号中放入属性名，是检查元素是否具有这个属性，
              只要元素有这个属性，不论属性是什么值，都可以被选中。
              </li>
              <li>
                第二种，[att=val]
              精确匹配，检查一个元素属性的值是否是 val。
              </li>
              <li>
                第三种，[att~=val]
              多种匹配，检查一个元素的值是否是若干值之一，
              这里的 val 不是一个单一的值了，可以是用空格分隔的一个序列。
              </li>
              <li>
                第四种，[att|=val]
              开头匹配，检查一个元素的值是否是以 val 开头，
              它跟精确匹配的区别是属性只要以 val 开头即可，后面内容不管。
              </li>
            </ul>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>伪类选择器</h2>
            <p>
              一系列由 CSS 规定好的选择器，它们以冒号开头，伪类有普通型和函数型。
            </p>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>链接与行为伪类选择器</h2>
            <ul>
              <li>:link 表示未访问过的链接。</li>
              <li>:visited 表示已经访问过的链接。</li>
              <li>:hover 表示鼠标悬停在上的元素。</li>
              <li>:active 表示用户正在激活这个元素，如用户按下按钮，鼠标还未抬起时，这个按钮就处于激活状态。</li>
              <li>:focus 表示焦点落在这个元素之上。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>布局</h2>
            <img src="assets/css/layout.png">
          </section>
          <section class="slide">
            <h2>Flex布局</h2>
            <img src="assets/css/flex.png">
            <p>
              容器默认存在两根轴：水平的主轴（main axis）和垂直的交叉轴（cross axis）。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>display flex</h2>
            <img src="assets/css/01-container.svg">
            <p>
              采用 Flex 布局的元素，称为 Flex 容器（flex container），简称"容器"。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>display flex</h2>
            <img src="assets/css/02-items.svg">
            <p>
              它的所有子元素自动成为容器成员，称为 Flex 项目（flex item），简称"项目"。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>flex-direction</h2>
            <img src="assets/css/flex-direction.svg">
            <p>
              flex-direction属性决定主轴的方向（即项目的排列方向）。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>flex-direction</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .box {
                flex-direction: row | row-reverse | column | column-reverse;
              }
            </code></pre>
              <p>flex-direction 可能有4个值：</p>
              <ul>
              <li>row（默认值）：主轴为水平方向，起点在左端。</li>
              <li>row-reverse：主轴为水平方向，起点在右端。</li>
              <li>column：主轴为垂直方向，起点在上沿。</li>
              <li>column-reverse：主轴为垂直方向，起点在下沿。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>flex-wrap</h2>
            <img class="w-3/4" src="assets/css/flex-wrap.svg">
            <p>
              默认情况下，项目都排在一条线（又称"轴线"）上。
              flex-wrap属性定义，如果一条轴线排不下，如何换行。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>flex-wrap</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .box {
                flex-wrap: nowrap | wrap | wrap-reverse;
              }
            </code></pre>
              <p>flex-wrap 可能有3个值：</p>
              <ul>
              <li>nowrap（默认）：不换行。</li>
              <li>wrap：换行，第一行在上方。</li>
              <li>wrap-reverse：换行，第一行在下方。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>justify-content</h2>
            <img class="w-1/4 h-auto" src="assets/css/justify-content.svg">
            <p>
              justify-content属性定义了项目在主轴上的对齐方式。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>justify-content</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .box {
                justify-content: flex-start | flex-end | center | space-between | space-around;
              }
            </code></pre>
            <p>justify-content 可能有5个值：</p>
            <ul>
              <li>flex-start（默认值）：左对齐</li>
              <li>flex-end：右对齐</li>
              <li>center： 居中</li>
              <li>space-between：两端对齐，项目之间的间隔都相等。</li>
              <li>space-around：每个项目两侧的间隔相等。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>align-items</h2>
            <img class="w-1/3 h-auto" src="assets/css/align-items.svg">
            <p>
              align-items属性定义项目在交叉轴上如何对齐。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>align-items</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .box {
                align-items: flex-start | flex-end | center | baseline | stretch;
              }
            </code></pre>
            <p>align-items 可能有5个值：</p>
            <ul>
              <li>flex-start：交叉轴的起点对齐。</li>
              <li>flex-end：交叉轴的终点对齐。</li>
              <li>center：交叉轴的中点对齐。</li>
              <li>baseline: 项目的第一行文字的基线对齐。</li>
              <li>stretch（默认值）：如果项目未设置高度或设为auto，将占满整个容器的高度。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>align-content</h2>
            <img class="w-1/3 h-auto" src="assets/css/align-content.svg">
            <p>
              align-content属性定义了多根轴线的对齐方式。
              如果项目只有一根轴线，该属性不起作用。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>align-content</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .box {
                align-content: flex-start | flex-end | center | space-between | space-around | stretch;
              }
            </code></pre>
            <p>align-content 可能有6个值：</p>
            <ul>
              <li>flex-start：与交叉轴的起点对齐。</li>
              <li>flex-end：与交叉轴的终点对齐。</li>
              <li>center：与交叉轴的中点对齐。</li>
              <li>space-between：与交叉轴两端对齐，轴线之间的间隔平均分布。</li>
              <li>space-around：每根轴线两侧的间隔都相等。</li>
              <li>stretch（默认值）：轴线占满整个交叉轴。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>order</h2>
            <img class="w-1/3 h-auto" src="assets/css/order.svg">
            <p>
              order属性定义项目的排列顺序。
              数值越小，排列越靠前，默认为0。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>order</h2>
            <img class="w-1/3 h-auto" src="assets/css/order.svg">
            <pre><code class="hljs" data-trim data-line-numbers>
              .item {
                order: &lt;integer&gt;;
              }
            </code></pre>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>flex-grow</h2>
            <img src="assets/css/flex-grow.svg">
            <p>
              flex-grow属性定义项目的放大比例，
              默认为0，即如果存在剩余空间，也不放大。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>flex-grow</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .item {
                flex-grow: &lt;number&gt; ; /* default 0 */
              }
            </code></pre>
            <p>
              如果所有项目的flex-grow属性都为1，则它们将等分剩余空间（如果有的话）。<br/>
              如果一个项目的flex-grow属性为2，其他项目都为1，则前者占据的剩余空间将比其他项多一倍。
            </p>
          </section>
          <section class="slide" data-background-color="#ffffff">
            <h2>flex</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .item {
                flex: none | [ &lt;'flex-grow'&gt; &lt;'flex-shrink'&gt;? || &lt;'flex-basis'&gt; ]
              }
            </code></pre>
            <p>
              flex属性是flex-grow, flex-shrink 和 flex-basis的简写，默认值为0 1 auto。后两个属性可选。
            </p>
            <p>
              比如设置 flex: 1，自动撑满剩余空间。
            </p>
          </section>
          <section class="slide" data-background-iframe="examples/flexboxfroggy/index.html">
            <!-- 看iframe flexboxfroggy 示例 -->
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>CSS transition 渐变动画</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              .bio-image-wrapper:hover  .bio-image{
                transform: scale(1.2) rotate(-8deg);
                transition: transform .2s ease-out;
              }
            </code></pre>
            <figure class="bio-image-wrapper md:flex rounded-xl p-8 md:p-0">
              <img class="bio-image w-48 h-48 rounded-full md-auto mx-auto mt-3.5" src="assets/author.jpg" />
            </figure>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>CSS transition 渐变动画</h2>
            <p>
              transition 有四个部分：
            </p>
            <ul>
              <li>transition-property 要变换的属性；</li>
              <li>transition-duration 变换的时长；</li>
              <li>transition-timing-function 时间曲线；</li>
              <li>transition-delay 延迟。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2 class="animate__animated animate__infinite animate__bounce">CSS animation 帧动画</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              @keyframes mykf {
                from {background: red;}
                to {background: yellow;}
              }

              div {
                  animation:mykf 5s infinite;
              }
            </code></pre>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>CSS animation 帧动画</h2>
            <p>
              animation 分成六个部分：
            </p>
            <ul>
              <li>animation-name 动画的名称，这是一个 keyframes 类型的值，keyframes 产生一种数据，用于定义动画关键帧；</li>
              <li>animation-duration 动画的时长；</li>
              <li>animation-timing-function	动画的时间曲线；</li>
              <li>animation-delay	动画开始前的延迟；</li>
              <li>animation-iteration-count	动画的播放次数；</li>
              <li>animation-direction	动画的方向</li>
            </ul>
          </section>
        </section>
        <!-- #endregion CSS Guide -->

        <!-- #region JavaScript Guide -->
        <section class="slide javascript-guide">
          <section class="slide" data-background-color="#ffc19f">
            <h1>JavaScript</h1>
            <p>
              一门用途十分广泛、而又备受指责的编程语言。
            </p>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>7 种数据类型</h2>
            <table>
              <thead>
                <tr>
                  <th>类型</th>
                  <th>值示例</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>Undefined</td>
                  <td>只有一个值：undefined</td>
                </tr>
                <tr>
                  <td>Null</td>
                  <td>只有一个值：null</td>
                </tr>
                <tr>
                  <td>Boolean</td>
                  <td>只有两个值：true/false</td>
                </tr>
                <tr>
                  <td>String</td>
                  <td>所有字符串，'Hello World'</td>
                </tr>
                <tr>
                  <td>Number</td>
                  <td>所有数字(包括浮点数)，123</td>
                </tr>
                <tr>
                  <td>Symbol</td>
                  <td>符号类型，Symbol.iterator</td>
                </tr>
                <tr>
                  <td>Object</td>
                  <td>引用数据类型，{}</td>
                </tr>
              </tbody>
            </table>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>Undefined 跟 Null 的区别</h2>
            <img class="w-3/4" src="assets/js/undefined-vs-null.png">
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>类型检测</h2>
            <img class="w-1/3" src="assets/js/type-check.jpg">
            <ul>
              <li>typeof 可以用来区分基本类型还是对象类型</li>
              <li>Object.prototype.toString 是可以准确识别对象对应的基本类型</li>
            </ul>
          </section>
          <section class="slide">
            <h2>函数</h2>
            <p>
              函数是一等公民。
            </p>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>call stack / 函数调用栈</h2>
            <p>
              JavaScript代码在执行时，会进入一个执行上下文中。<br/>
              执行上下文可以理解为当前代码的运行环境。
            </p>
            <p>
              JavaScript中的运行环境主要包括以下三种情况：
            </p>
            <ul>
              <li>全局环境：代码运行起来后会首先进入全局环境;</li>
              <li>函数环境：当函数被调用执行时，会进入当前函数中执行代码;</li>
              <li>eval环境：不建议使用，这里不做介绍。</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>call stack / 函数调用栈</h2>
            <p>
              JavaScript引擎会以栈的方式来处理它们，这个栈被称作函数调用栈（call stack）。<br/>
              函数调用栈规定了JavaScript代码的执行顺序。<br/>
              栈底永远都是全局上下文(在浏览器中是window)，
              栈顶则是当前正在执行的上下文（当前函数）。
            </p>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>call stack demo</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // call stack demo
              var color = 'blue';
              function changeColor() {
                var anotherColor = 'red';

                function swapColors() {
                  debugger;
                  var tempColor = anotherColor;
                  anotherColor = color;
                  color = tempColor;
                }

                swapColors();
              }
              changeColor();
            </code></pre>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>call stack / 函数调用栈</h2>
            <img src="assets/js/call-stack.png">
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>scope / 作用域</h2>
            <p>
              在JavaScript中，作用域是用来规定变量与函数可访问范围的一套规则。
            </p>
            <p>
              最常见的作用域，
            </p>
            <ul>
              <li>全局作用域</li>
              <li>函数作用域</li>
              <li>块级作用域</li>
            </ul>
          </section>
          <section class="slide">
            <h2>全局作用域</h2>
            <p>
              全局上下文中的变量对象实际上就是window对象本身，<br/>
              因此在全局上下文中声明的变量与方法其实就变成了window的属性与方法。<br/>
            </p>
            <p>
              在实践中，为了避免多人协作带来的冲突，<br/>
              我们要尽可能少地自定义全局变量与方法。
            </p>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>函数作用域</h2>
            <p>
              函数作用域中声明的变量与方法，<br/>
              只能被下层子作用域访问，<br/>
              而不能被其他不相干的作用域访问。
            </p>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>scope demo</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // scope demo
              function foo() {
                var a = 20;
                var b = 30;
              }
              foo();
              function bar() {
                return a + b;
              }
              bar(); // 因为作用域限制，bar中无法访问到变量a和b
            </code></pre>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>scope demo</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // scope demo
              function foo() {
                var a = 20;
                var b = 30;
                function bar() {
                  debugger;
                  return a + b;
                }
                return bar();
              }
              foo(); // 50 bar处在foo的作用域，能够访问到变量a和b
            </code></pre>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>scope demo</h2>
            <img src="assets/js/scope.png">
          </section>
          <section data-background-color="#06406c">
            <h2>块级作用域</h2>
            <p>
              在ES6以后，ECMAScript有了块级作用域——let const。
            </p>
          </section>
          <section class="slide">
            <h2>块级作用域</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // block scope demo
              var arr = [1, 2, 3, 4, 5];
              for(let i = 0; i &lt; arr.length; i++) {
                console.log('do something by ', i);
              }
              console.log(i); // Uncaught ReferenceError: i is not defined
            </code></pre>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>块级作用域</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // block scope demo
              var arr = [1, 2, 3, 4, 5];
              for(var i = 0; i &lt; arr.length; i++) {
                console.log('do something by ', i);
              }
              console.log(i); // 5
            </code></pre>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>closure / 闭包</h2>
            <p>
              闭包是指这样的作用域（foo），它包含了一个函数（fn1），
              这个函数（fn1）可以调用被这个作用域所封闭的变量（a）、函数或者闭包等内容。
              通常我们通过闭包所对应的函数来获得对闭包的访问。
            </p>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>closure / 闭包</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // closure demo
              var fn;
              function foo() {
                var a = 2;
                function baz() {
                  debugger;
                  console.log(a);
                }
                fn = baz;
              }
              function bar() {
                fn();
              }
              foo();
              bar(); // 2
            </code></pre>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>closure / 闭包</h2>
            <img src="assets/js/closure.png">
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>this 引用</h2>
            <p>
              一个函数内部的this到底指向谁是非常灵活且不确定的，这也是this难以被真正理解的原因所在。
            </p>
          </section>
          <section class="slide">
            <h2>this 引用</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // this demo
              var a = 10;
              var obj = { a: 20 };
              function fn() {
                debugger;
                console.log(this.a);
              }
              fn(); // 10
              fn.call(obj); // 20
            </code></pre>
            <p>通过a值的不同表现，我们可以知道this分别指向了window与obj。</p>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>显式改变this的引用</h2>
            <ul>
              <li>call：call的第一个参数是为函数内部指定this指向，后续的参数则是函数执行时所需要的参数，一个个传递。</li>
              <li>apply：apply的第一个参数与call相同，为函数内部this指向，而函数的参数，则以数组的形式传递，作为apply的第二个参数。</li>
              <li>bind：当函数调用bind时，函数并不会立即执行，而是返回一个新的函数。</li>
            </ul>
            <p>
              当函数调用call/appy时，函数的内部this被显式指定，并且函数会立即执行。
            </p>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>模块化</h2>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>匿名闭包 ：IIFE 模式</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              var Module = (function(){
                var _private = "safe now";
                var foo = function(){
                    console.log(_private)
                }

                return {
                    foo: foo
                }
              })()

              Module.foo();
              Module._private; // undefined
            </code></pre>
            <p>函数之前是 JavaScript 唯一的 Local Scope</p>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>CommonJS / Node.js</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // math.js
              exports.add = function(a, b){
                  return a + b;
              }
              ```
              ```javascript
              // main.js
              var math = require('math')      // ./math in node
              console.log(math.add(1, 2));    // 3
            </code></pre>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>AMD / require.js</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // AMD recommended style
              define(["a", "b"], function(a, b){ // 依赖前置
                  a.doSomething();
                  b.doSomething();
              })
            </code></pre>
          </section>
          <section class="slide">
            <h2>ES 6 module</h2>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>Single Default Module</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // math.js
              export default math = {
                  PI: 3.14,
                  foo: function(){}
              }
            </code></pre>
            <pre><code class="hljs" data-trim data-line-numbers>
              // app.js
              import math from "./math";
              math.PI
            </code></pre>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>Named Exports</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // export Declaration
              export function foo(){
                  console.log('I am not bar.');
              }
            </code></pre>
            <pre><code class="hljs" data-trim data-line-numbers>
              // export VariableStatement;
              export const PI = 3.14;
              export let bar = foo;   // function expression
            </code></pre>
            <pre><code class="hljs" data-trim data-line-numbers>
              // export { ExportsList }
              const PI = 3.14;
              const foo = function(){};

              export { PI, foo };
            </code></pre>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>Importing Named Exports</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // import { ImportsList } from "module-name"
              import { PI } from "./math";
              import { PI, foo } from "module-name";
            </code></pre>
            <pre><code class="hljs" data-trim data-line-numbers>
              // import IdentifierName as ImportedBinding
              import { foo as bar } from "./math";
              bar();  // use alias bar
            </code></pre>
            <pre><code class="hljs" data-trim data-line-numbers>
              // import NameSpaceImport
              import * as math from "./math";
              math.PI
              math.foo()
            </code></pre>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>异步：Promise、async & await</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              function fn() {
                return new Promise(function (resolve, reject) {
                  setTimeout(function () {
                    resolve(30);
                  }, 1000);
                });
              }
              var foo = async function() {
                var t = await fn();
                console.log(t);
                console.log('next code');
              }
              foo();
            </code></pre>
          </section>
        </section>
        <!-- #endregion JavaScript Guide -->

        <!-- #region React Guide -->
        <section class="slide react-guide">
          <section class="slide" data-background-color="#fff8c9">
            <h1>React</h1>
            <p>
              用于构建用户界面的 JavaScript 库。
            </p>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>1、组件式开发</h2>
            <img class="h-2/3" src="assets/react/thinking-in-react-components.png">
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>1、组件式开发 - Demo</h2>
            <img class="h-2/3" src="assets/react/todo-list.png">
          </section>
          <section class="slide" data-background-color="#06406c">
            <h3>1、组件式开发 - 描述UI的JSX语法</h3>
            <pre><code class="hljs" data-trim data-line-numbers>
              const element = &lt;h1 className="greeting"&gt;Hello, world!&lt;/h1&gt;;
            </code></pre>
            <p>被转译成React.createElement()函数调用: </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              const element = React.createElement(
                'h1',
                {className: 'greeting'},
                'Hello, world!'
              );
            </code></pre>
            <p>实际上创建了一个这样的对象: </p>
            <pre><code class="hljs" data-trim data-line-numbers>
              const element = {
                type: 'h1',
                props: {
                  className: 'greeting',
                  children: 'Hello, world!'
                }
              };
            </code></pre>
          </section>
          <section class="slide">
            <h3>1、组件式开发 - 描述UI的JSX语法</h3>
            <p>
              这些与 html 元素类似的标签元素，被称之为 React 元素。<br/>
              他们是不可变对象。<br/>
              一个元素就像电影中的一帧，它代表了某个特定时刻的 UI。
            </p>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>2、数据驱动UI</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              const [todos] = useTodos();
            </code></pre>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;ul className="todo-list"&gt;
                {visibleTodos.map(todo =&gt; (
                  &lt;TodoItem key={todo.id} todo={todo} /&gt;
                ))}
              &lt;/ul&gt;
            </code></pre>
            <ul>
              <li>以数据为中心;</li>
              <li>单向数据流;</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>2、数据驱动UI</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;ul className="todo-list"&gt;
                {visibleTodos.map(todo =&gt; (
                  &lt;TodoItem key={todo.id} todo={todo} /&gt;
                ))}
              &lt;/ul&gt;
            </code></pre>
            <pre><code class="hljs" data-trim data-line-numbers>
              export default function TodoItem({ todo }) {
                return (
                  &lt;li&gt;
                    &lt;div className="view"&gt;
                      &lt;label&gt;{todo.label}&lt;/label&gt;
                      &lt;button className="destroy" onClick={onDelete} /&gt;
                    &lt;/div&gt;
                  &lt;/li&gt;
                );
              }
            </code></pre>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>父子组件通信</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              &lt;ul className="todo-list"&gt;
                {visibleTodos.map(todo =&gt; (
                  &lt;TodoItem key={todo.id} todo={todo} /&gt;
                ))}
              &lt;/ul&gt;
            </code></pre>
            <ul>
              <li>父向子： Props</li>
              <li>子向父： Callback</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>跨父子组件通信</h2>
            <ul>
              <li>Context</li>
              <li>Redux、Mobx等全局状态管理框架</li>
              <li>RxJS等事件流处理框架</li>
              <li>EventEmiter等发布/订阅模式框架</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>3、事件响应</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              export default function TodoItem({ todo }) {
                return (
                  &lt;li&gt;
                    &lt;div className="view"&gt;
                      &lt;input type="checkbox" onChange={onDone} checked={todo.done}/&gt;
                      &lt;label&gt;{todo.label}&lt;/label&gt;
                      &lt;button className="destroy" onClick={onDelete} /&gt;
                    &lt;/div&gt;
                  &lt;/li&gt;
                );
              }
            </code></pre>
          </section>
          <section class="slide">
            <h2>生命周期</h2>
          </section>
          <section class="slide" data-background-iframe="examples/react-lifecycle-methods-diagram/dist/index.html">
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>React Hooks</h2>
            <ul>
              <li>useState</li>
              <li>useEffect</li>
              <li>useRef</li>
              <li>...</li>
            </ul>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>useState</h2>
            <p>组件内部状态数据：state</p>
            <pre><code class="hljs" data-trim data-line-numbers>
              function Coutner() {
                // 利用数组结构得到两个变量
                // count：表示定义的数据
                // setCount：修改该数据的方法
                // useState：从闭包数据中取出 count 的值，0 仅表示默认值
                const [count, setCount] = useState(0)
                
                return (
                  &lt;div&gt;{count}&lt;/div&gt;
                  &lt;button onClick={() =&gt; setCount(count + 1)}&gt;递增&lt;/button&gt;
                )
              }
            </code></pre>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>useEffect</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // 中括号表示参数可选
              useEffect(effct[, deps])
            </code></pre>
            <p>
              第一个参数就是副作用函数 effect。<br/>
              第二个参数表示依赖项，是一个可选参数。
              当不传入该参数时，每次 UI 渲染 effect 函数都会执行。
            </p>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>useEffect</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              function Demo() {
                const [count, setCount] = useState(0)
                const [show, setShow] = useState(false)
                
                useEffect(() =&gt; {
                  // do something
                }, [count])
                
                useEffect(() =&gt; {
                  // do other something
                }, [show])
              
                ...
              }
            </code></pre>
            <p>
              只有当依赖项中 state 发生变化时，effect 才会与之对应的执行。
            </p>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>useEffect</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              const [list, setList] = useState(0);

              // DOM渲染完成之后 effect 函数执行
              useEffect(() =&gt; {
                recordListApi().then(res =&gt; {
                  setList(res.data);
                })
              }, []);
            </code></pre>
            <p>
              我们还可以传入空数组作为依赖项，用于表示依赖项不会发生变化。<br/>
              因此，空数组对应的 effect，就只会在初始化时执行一次，以后就再也不会执行了。
            </p>
          </section>
          <section class="slide">
            <h2>useEffect - 清除副作用</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              useEffect(() =&gt; {
                // dosomething
                
                // 定义 clear effect 函数
                return () =&gt; {
                  // clear something
                }
              }, [])
            </code></pre>
            <p>
              可以定义一个回调函数由 effect 执行时返回，该函数就是 clear effect 函数。<br/>
              clear effect 在下次 effect 执行之前执行，也会在组件销毁之前执行一次。
            </p>
          </section>
          <section class="slide" data-background-color="#f2f2f2">
            <h2>useRef</h2>
            <p>
              使用 useState 定义的数据会被监控，他们的变化会直接导致 UI 的变化。<br/>
              当该需要持久化的数据不会跟 UI 变化产生关系时，我们就需要用到 useRef。
            </p>
          </section>
          <section class="slide" data-background-color="#fff8c9">
            <h2>useRef</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              const ref = useRef(initialValue);
            </code></pre>
            <p>
              useRef 是一个返回可变引用对象的函数。 <br/>
              该对象 .current 属性的初始值为 useRef 传入的参数 initialValue。
            </p>
            <p>
              当一个数据需要在 re-render 的过程中持久稳定的保持该数据对应的状态时，我们可以考虑使用 useRef.
            </p>
          </section>
          <section class="slide" data-background-color="#ffc19f">
            <h2>useRef</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              import {useRef} from "react";
              export default function Demo() {
                const inputRef = useRef&lt;HTMLInputElement&gt;(null);
                const focusTextInput = () =&gt; {
                  if (inputRef.current) { 
                    inputRef.current.focus();
                  }
                }
                return (&lt;&gt;
                    &lt;input type="text" ref={inputRef} /&gt;
                    &lt;button onClick={focusTextInput}&gt;点击我让input组件获得焦点&lt;/button&gt;
                  &lt;/&gt;);
              }
            </code></pre>
            <p>
              useRef 是一个返回可变引用对象的函数。 <br/>
              该对象 .current 属性的初始值为 useRef 传入的参数 initialValue。
            </p>
          </section>
          <section class="slide" data-background-color="#348fd4">
            <h2>useRef</h2>
            <p>
              使用useRef可以访问DOM节点或React元素。<br/>
              React函数式组件，通过useRef得不到React元素。
            </p>
          </section>
          <section class="slide" data-background-color="#06406c">
            <h2>forwardRef</h2>
            <pre><code class="hljs" data-trim data-line-numbers>
              // 官网的案例
              const FancyButton = React.forwardRef((props, ref) =&gt; (
                &lt;button ref={ref} className="FancyButton"&gt;
                  {props.children}
                  &lt;/button&gt;
              ));

              // 你可以直接获取 DOM button 的 ref：
              const ref = React.createRef();
              &lt;FancyButton ref={ref}&gt;Click me!&lt;/FancyButton&gt;;
            </code></pre>
            <p>
              forwardRef方法能够传递ref引用。
            </p>
          </section>
        </section>
        <!-- #endregion React Guide -->

        <section class="slide">
          <h2>参考资料</h2>
          <ul>
            <li>MDN: https://developer.mozilla.org/zh-CN/</li>
            <li>Excalidraw: https://excalidraw.com/</li>
            <li>重学前端：https://time.geekbang.org/column/intro/100023201</li>
            <li>Flex：https://css-tricks.com/snippets/css/a-guide-to-flexbox/</li>
            <li>Flexbox Froggy: http://flexboxfroggy.com/</li>
            <li>Todos： http://todomvc.com/</li>
            <li>React 知命境系列：https://mp.weixin.qq.com/s/thGjdaR5IwhAwUWF4jPzmw</li>
          </ul>
        </section>
      </div>
    </div>
    
  </body>
</html>
